

function Promise(executor) {
    let self = this;
    this.PromiseState = 'pending';
    this.PromiseResult = undefined;
    this.callbacks = [];

    function resolve(value) {
        if (self.PromiseState !== 'pending') return;
        // 1. 改变状态
        // 2. 结果值
        self.PromiseState = 'fulfilled';
        self.PromiseResult = value;
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onResolved();
            })
        })
    }
    function reject(reason) {
        if (self.PromiseState !== 'pending') return;
        self.PromiseState = 'rejected';
        self.PromiseResult = reason;
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onRejected();
            })
        })
    }
    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

Promise.prototype.then = function (onResolved, onRejected) {
    let self = this;
    return new Promise((resolve, reject) => {
        if (typeof onRejected !== 'function') {
            onRejected = reason => {
                throw reason;
            }
        }
        if (typeof onResolved !== 'function') {
            onResolved = value => value;
        }
        function changeState(type) {
            try {
                let rs = type(self.PromiseResult);
                if (rs instanceof Promise) {
                    rs.then(resolve, reject);
                } else {
                    resolve(rs);
                }
            } catch (e) {
                reject(e);
            }
        }

        if (this.PromiseState === 'fulfilled') {
            setTimeout(() => {
                changeState(onResolved)
            })
        }
        if (this.PromiseState === 'rejected') {
            setTimeout(() => {
                changeState(onRejected)
            })
        }
        if (this.PromiseState === 'pending') {
            this.callbacks.push({
                onResolved: () => {
                    changeState(onResolved);
                },
                onRejected: () => {
                    changeState(onRejected);
                }
            })
        }
    })

}

Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}

Promise.resolve = function (n) {
    return new Promise((resolve, reject) => {
        if (n instanceof Promise) {
            n.then(resolve, reject);
        } else {
            resolve(n);
        }
    })
}

Promise.all = function(arr){
    let count = 0;
    let resultLength = arr.length;
    let resultArr = new Array(resultLength);
    
    return new Promise((resolve,reject)=>{
        for(let i = 0; i < arr.length; i++){
            let cur = arr[i];
            cur.then(value=>{
                resultArr[i] = value;
                count++;
                if(count === resultLength){
                    resolve(resultArr);
                }
            },reason=>{
                reject(reason);
            })
        }
        
    })
}

Promise.race = function(promiseArr){
    return new Promise((resolve, reject)=>{
        for(let i = 0; i < promiseArr.length;i++){
            promiseArr[i].then(value=>{
                resolve(value);
            },reason=>{
                reject(reason);
            })
        }
    })
}

// Promise.all = function (promises) {
//     // 返回一个新的promise
//     return new Promise((resolve, reject) => {
//       // 已成功的数量
//       let resolvedCount = 0
//       // 待处理的promises数组的长度
//       const promisesLength = promises.length
//       // 准备一个保存成功值的数组
//       const values = new Array(promisesLength)
//       // 遍历每个待处理的promise
//       for (let i = 0; i < promisesLength; i++) {
//         // promises中元素可能不是一个数组, 需要用resolve包装一下
//         Promise.resolve(promises[i]).then(
//           value => {
//             // 成功当前promise成功的值到对应的下标
//             values[i] = value
//             // 成功的数量加1
//             resolvedCount++
//             // 一旦全部成功
//             if(resolvedCount===promisesLength) {
//               // 将所有成功值的数组作为返回promise对象的成功结果值
//               resolve(values)
//             }
//           },
//           reason => {
//            // 一旦有一个promise产生了失败结果值, 将其作为返回promise对象的失败结果值
//             reject(reason)
//           }
//         )
//       }
//     })
//   }